package com.qf.shiro;


import org.springframework.util.StringUtils;
import com.qf.pojo.DtsAdmin;
import com.qf.service.AdminService;
import com.qf.service.PermissionService;
import com.qf.service.RoleService;
import com.qf.util.bcrypt.BCryptPasswordEncoder;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;

public class AdminAuthorizingRealm extends AuthorizingRealm {

    @Autowired
    private AdminService adminService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private PermissionService permissionService;


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1. 获取认证后的当前用户对象, 这里将参数强转成我们自己封装的用户实体类对象
        DtsAdmin admin = (DtsAdmin) getAvailablePrincipal(principalCollection);
        //根据用户对象获取角色ids
        Integer[] roleIds = admin.getRoleIds();
        //根据角色id集合到数据库中查找对应的角色名称集合
        Set<String> roleSet = roleService.queryByIds(roleIds);

        //根据角色id集合，到数据库中查询对应的权限字符串集合
        Set<String> permSet = permissionService.queryPermissionByRoleIds(roleIds);
        //将角色名称集合，和权限字符串集合交给shiro框架
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        info.setRoles(roleSet);
        info.setStringPermissions(permSet);
        //返回封装后的shiro权限对象
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        //获取用户页面输入的用户名，密码
        UsernamePasswordToken UserNameAndPwd = (UsernamePasswordToken) authenticationToken;
        String username = UserNameAndPwd.getUsername();
        String password = new String(UserNameAndPwd.getPassword());

        //判断用户名是否为空，为空返回异常信息
        if (StringUtils.isEmpty(username)){
            throw new AccountException("用户名不能为空");
        }
        if (StringUtils.isEmpty(password)){
            throw new AccountException("密码不能为空");
        }
        //根据用户名，获取用户对象集合
        List<DtsAdmin> userList = adminService.findAdminUserName(username);
        //判断如果获取不到用户对象，返回异常提示信息
        if (userList==null||userList.size()==0){
            throw new UnknownAccountException("用户名错误");
        }
        if (userList.size()>=2){
            throw new UnknownAccountException("存在同名账户，请联系管员");
        }
        DtsAdmin admin = userList.get(0);
        BCryptPasswordEncoder ecoder = new BCryptPasswordEncoder();
        //BCrypt工具类进行校验, 密码使用的BCrypt算法进行的加密
        //第一个参数是明文密码, 第二个参数是加密后的密码, 返回校验结果
        if (!ecoder.matches(password,admin.getPassword())){
            throw  new UnknownAccountException("密码错误");
        }

        //8. 封装shiro指定的对象交给shiro框架处理
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(admin, password, this.getName());

        return info;
    }
}
